﻿using System;
using System.Collections.Generic;

namespace Borg.Framework
{
    internal class RegisterCommand : ICommand
    {
        private readonly string[][] _arguments =
            new[]
                {
                    new[] { "PluginInfo", "ExtensionTypeInfo", "ExtensionInfo", "PlugTypeInfo", "SlotInfo" },
                    new string[0], new[] { "in" },
                    new[] { "ExtensionInfo", "SlotInfo" }, new string[0]
                };

        public IEnumerable<string> GetArguments(string[] command, int pos)
        {
            string[] strArray = null;
            switch (pos)
            {
                case 0:
                case 2:
                case 3:
                    return _arguments[pos];

                case 1:
                case 4:
                    if (command.Length >= (pos + 1))
                    {
                        var str = command[pos];

                        if (str != null)
                        {
                            int i;

                            if (str != "PluginInfo")
                            {
                                switch (str)
                                {
                                    case "ExtensionTypeInfo":
                                        strArray = new string[Runtime.Repository.ExtensionTypeInfos.Count];
                                        for (i = 0; i < strArray.Length; i++)
                                            strArray[i] = Runtime.Repository.ExtensionTypeInfos[i].Name;
                                        return strArray;
                                    
                                    case "ExtensionInfo":
                                        strArray = new string[Runtime.Repository.ExtensionInfos.Count];
                                        for (i = 0; i < strArray.Length; i++)
                                            strArray[i] = Runtime.Repository.ExtensionInfos[i].Name;
                                        return strArray;
                                    
                                    case "PlugTypeInfo":
                                        strArray = new string[Runtime.Repository.PlugTypeInfos.Count];
                                        for (i = 0; i < strArray.Length; i++)
                                            strArray[i] = Runtime.Repository.PlugTypeInfos[i].Name;
                                        return strArray;
                                    
                                    case "SlotInfo":
                                        strArray = new string[Runtime.Repository.SlotInfos.Count];
                                        for (i = 0; i < strArray.Length; i++)
                                            strArray[i] = Runtime.Repository.SlotInfos[i].Name;
                                        return strArray;
                                }
                            }
                            else
                            {
                                strArray = new string[Runtime.Repository.PluginInfos.Count];

                                for (i = 0; i < strArray.Length; i++)
                                    strArray[i] = Runtime.Repository.PluginInfos[i].Name;
                            }
                        }

                        return strArray;
                    }

                    return new string[0];
            }

            return null;
        }

        private string Register(string[] command)
        {
            string str;

            if (command.Length < 2)
                return "Too few arguments.";

            if (!RuntimeCommands.ContainsArgument(command[1], _arguments[0]))
                return string.Format("Invalid argument \"{0}\".", command[1]);

            if (command.Length < 3)
                return "Too few arguments.";

            var elements = RuntimeCommands.Find(command, 1, out str);

            if (elements.Length == 0)
                return str;

            string cmd = command[1];

            if (cmd != null)
            {
                if (cmd != "PluginInfo")
                {
                    RepositoryElement[] repository;

                    switch (cmd)
                    {
                        case "ExtensionTypeInfo":
                            if (command.Length < 4)
                                foreach (ExtensionTypeInfo eti in elements)
                                    eti.RegisterPlugs();
                            else
                            {
                                if (!command[3].Equals("in", StringComparison.CurrentCultureIgnoreCase))
                                    return string.Format("\"in\" expected.", new object[0]);

                                if (command.Length < 5)
                                    return "Too few arguments.";

                                if (command[4] != "ExtensionInfo")
                                    return string.Format("\"ExtensionInfo\" argument expected.", new object[0]);

                                if (command.Length < 6)
                                    return "Too few arguments.";

                                repository = RuntimeCommands.Find(command, 4, out str);

                                foreach (ExtensionTypeInfo eti in elements)
                                    foreach (ExtensionInfo ei in repository)
                                        eti.RegisterPlugs(ei);
                            }
                            break;

                        case "ExtensionInfo":
                            foreach (ExtensionInfo ei in elements)
                                ei.RegisterInSlots();
                            break;

                        case "PlugTypeInfo":
                            if (command.Length < 4)
                                foreach (PlugTypeInfo pti in elements)
                                    pti.Register();
                            else
                            {
                                if (!command[3].Equals("in", StringComparison.CurrentCultureIgnoreCase))
                                    return string.Format("\"in\" expected.", new object[0]);

                                if (command.Length < 5)
                                    return "Too few arguments.";

                                if (command[4] != "SlotInfo")
                                    return string.Format("\"SlotInfo\" argument expected.", new object[0]);

                                if (command.Length < 6)
                                    return "Too few arguments.";

                                repository = RuntimeCommands.Find(command, 4, out str);

                                foreach (PlugTypeInfo pti in elements)
                                    foreach (SlotInfo si in repository)
                                        pti.Register(si);
                            }
                            break;

                        case "SlotInfo":
                            foreach (SlotInfo si in elements)
                                si.Register();
                            break;
                    }
                }
                else
                    foreach (PluginInfo pi in elements)
                        pi.Register();
            }

            return string.Empty;
        }

        public IEnumerable<string>[] Arguments
        {
            get { return _arguments; }
        }

        public CommandHandler Handler
        {
            get { return Register; }
        }

        public string Help
        {
            get { return "Help for command \"register\""; }
        }

        public string Name
        {
            get { return "register"; }
        }
    }
}

